package jfprincesstests.structures.negotiation;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import jfprincesstests.fakes.FakeActivator;
import jfprincesstests.fakes.FakeCmd;
import jfuzzyprincepless.agents.INegotiatingAgent;
import jfuzzyprincepless.algorithm.structure.*;
import jfuzzyprincepless.zarchive.algorithm.structure.ICommandConstruction;
import jfuzzyprincepless.zarchive.algorithm.structure.forcnstr.fuzzyfor.*;
import jfuzzyprincepless.zarchive.algorithm.structure.forcnstr.IExecuteForNegotiation;
import jfuzzyprincepless.zarchive.algorithm.structure.ifcnstr.INegotiationCondition;
import jfuzzyprincepless.zarchive.algorithm.structure.ifcnstr.NegotiationIfConstruction;
import jfuzzyprincepless.negotiation.*;
import jfuzzyprincepless.zarchive.variables.IFuzzySet;
import jfuzzyprincepless.zarchive.variables.FuzzySet;
import jfuzzyprincepless.zarchive.negotiation.ZArchNegotiationUtils;
import jfuzzyprincepless.zarchive.negotiation.services.IExecuteForService;
import jfuzzyprincepless.zarchive.negotiation.protocols.propositionnetwork.ExecuteForNegotiation;
import laboratoryQ.junit.ignore.patch.BaseTestCase;

public class TestNegotiationUtils extends BaseTestCase {
	@SuppressWarnings("unchecked")
	public void testAgentsExtraction() {
		List<IConstruction> constructions =
			new ArrayList<IConstruction>();
		assertEquals(
			0,
			ZArchNegotiationUtils.extractAgents(constructions).size()
		);
		assertEquals(
			1,
			ZArchNegotiationUtils.extractAgents(
				Arrays.asList(new FakeActivator(null))
			).size()
		);

		constructions.add(new FakeCmd(null, null));
		constructions.add(new FakeCmd(null, null));
		constructions.add(new FakeCmd(null, null));
		assertEquals(
			0,
			ZArchNegotiationUtils.extractAgents(constructions).size()
		);

		constructions.add(new FakeActivator(null));
		constructions.add(new FakeCmd(null, null));
		constructions.add(new FakeActivator(null));
		constructions.add(new FakeCmd(null, null));
		assertEquals(
			2,
			ZArchNegotiationUtils.extractAgents(constructions).size()
		);
		assertEquals(
			"[FakeActivator null, FakeActivator null]",
			Arrays.toString(
				ZArchNegotiationUtils.extractAgents(constructions)
					.toArray(INegotiatingAgent.EMPTY_ARRAY)
			)
		);

		List<INegotiatingAgent> agentsList =
			ZArchNegotiationUtils.extractAgents(constructions, constructions);
		assertEquals(
			4,
			agentsList.size()
		);
		assertEquals(
			"[FakeActivator null, FakeActivator null, FakeActivator null, FakeActivator null]",
			Arrays.toString(
				agentsList
					.toArray(INegotiatingAgent.EMPTY_ARRAY)
			)
		);
	}

	public void testAgentsExtractionFlags() {
		List<IConstruction> constructions =
			new ArrayList<IConstruction>();

		constructions.add(new FakeActivator(null));
		constructions.add(new FakeCmd(null, null));
		constructions.add(new FakeActivator(null));
		constructions.add(new FakeCmd(null, null));

		NegotiationIfConstruction ifContainsActivator =
			new NegotiationIfConstruction(
				INegotiationCondition.EMPTY_CONDITION,
				Arrays.<ICommandConstruction>asList(
					new FakeActivator(null)
				),
				ICommandConstruction.EMPTY_LIST
			);
		ifContainsActivator.extractAgentsFromConstructions();
		constructions.add(
			ifContainsActivator
		);
		assertEquals(
			2,
			ZArchNegotiationUtils.extractAgents(
				constructions,
				ZArchNegotiationUtils.CMD_IS_AGENT
			).size()
		);
		assertEquals(
			1,
			ZArchNegotiationUtils.extractAgents(
				constructions,
				ZArchNegotiationUtils.CMD_IS_EXPORTER
			).size()
		);
		assertEquals(
			3,
			ZArchNegotiationUtils.extractAgents(
				constructions,
				ZArchNegotiationUtils.CMD_IS_AGENT | ZArchNegotiationUtils.CMD_IS_EXPORTER
			).size()
		);
		assertEquals(
			"[FakeActivator null, FakeActivator null, FakeActivator null]",
			Arrays.toString(
				ZArchNegotiationUtils.extractAgents(constructions)
				.toArray(INegotiatingAgent.EMPTY_ARRAY)
			)
		);
	}

/*
 * NEVER used, archive
	// XX X: this method is neverused
	public static List<INegotiatingAgent> extractAgents(
		ICommandConstruction command
	) {
		List<ICommandConstruction> commands;
		if (command instanceof ChainCommand) {
			// FIXM E: ugly
			commands = null;//((ChainCommand)command).getCommandsList();
		} else {
			commands = Arrays.asList(command);
		}
		return extractAgents(commands);
	}

	public void testExtractAgentsFromOneCommand() {
		assertEquals(
			0,
			NegotiationUtils.extractAgents(
				new FakeCmd(null, null)
			).size()
		);
		assertEquals(
			1,
			NegotiationUtils.extractAgents(
				new FakeActivator(null)
			).size()
		);
		assertEquals(
			2,
			NegotiationUtils.extractAgents(
				new ChainCommand(
					new FakeCmd(null, null),
					new FakeCmd(null, null),
					new FakeCmd(null, null),
					new FakeActivator(null),
					new FakeActivator(null)
				)
			).size()
		);
	}
*/

	public void testDefaultNegotiationIteration() {
		final StringBuilder sb = new StringBuilder();
		final int[] remaind_ptr = new int[] { 1 };

		List<INegotiatingAgent> agentList =
			Arrays.<INegotiatingAgent>asList(
				new INegotiatingAgent() {
					public int count = 0;

					@Override
					public void onNegotiationStart(
						INegotiationContext context
					) {
					}

					@Override
					public boolean negotiate(
						INegotiationContext context
					) {
						sb.append(count++).append(";");
						return --remaind_ptr[0] > 0;
					}
				}
			);

		NegotiationUtils.defaultNegotiationIteration(
			agentList,
			new DefaultNegotiationContext()
		);
		assertEquals(
			"0;",
			sb.toString()
		);

		remaind_ptr[0] = 10;
		NegotiationUtils.defaultNegotiationIteration(
			agentList,
			new DefaultNegotiationContext()
		);
		assertEquals(
			"0;1;2;3;4;5;6;7;8;9;10;",
			sb.toString()
		);
	}

	@SuppressWarnings("unchecked")
	public void testMembershipGet() {
		IFuzzySet<Integer> fuzzySet =
			new FuzzySet<Integer>();
		fuzzySet.add(1, 0.1);
		fuzzySet.add(2, 0.2);
		fuzzySet.add(3, 0.3);

		final int[] forIterationsCounter_ptr = new int[] { 0 };

		final IExecuteForNegotiation<Integer>[] effn_ptr =
			new IExecuteForNegotiation[] { null };

		ICommandConstruction cmd =
			new ICommandConstruction() {
				@Override
				public void execute(IExecutionContext econtext) {
					INegotiationContext ncontext =
						(INegotiationContext) econtext;
					IExecuteForService<Integer> forServ =
						ncontext.getService(IExecuteForService.class);
					double cur = forServ.getCurrentElem();
					double mem = ZArchNegotiationUtils
						.getCurrentMembershipDegree(ncontext);
					assertEquals(cur / 10.0, mem);
					forIterationsCounter_ptr[0]++;
				}
			};
		INegotiationFuzzyFor<Integer> forLoop =
			new NegotiationFuzzyFor<Integer>(
				fuzzySet,
				cmd
			);

		IExecuteForNegotiation<Integer> effn =
			new ExecuteForNegotiation<Integer>(forLoop);
		effn_ptr[0] = effn;
		IExecutionContext context = effn.negotiate();
		effn.execute(context);

		assertEquals(3, forIterationsCounter_ptr[0]);
	}
}
